#ifndef DW_SYSTEM_BUFFER_H
#	define DW_SYSTEM_BUFFER_H

#include "system/resource.h"

namespace dw {
	namespace system {

class IBuffer
:	public IResource
,	public std::basic_streambuf< char >
{
public : //! @name Enums
	//! @{
	enum Usage
	{
		BU_STATIC,
		BU_DYNAMIC,
		BU_STREAM,
		BU_RENDERTARGET
	};

	enum Access
	{
		BA_READ_ONLY,
		BA_WRITE_ONLY,
		BA_READ_WRITE
	};

public : //! @name Construction & destruction
	//! @{
	IBuffer(Usage usage = BU_STATIC);
	//! @}

public : //! @name Commands
	//! @{
	//! @}
	virtual void resize(const uint32 size) = 0;
	virtual void lock(const uint32 offset, const uint32 size, const Access access) = 0;
	virtual void unlock() = 0;
	virtual void read(const uint32 offset, const uint32 size, void* dst) const = 0;
	virtual void write(const uint32 offset, const uint32 size, const void* src) = 0;
	void read(void* dst) const ;
	void write(const void* src);

public : //! @name Setup
	//! @{
	void setData(const uint32 i, const char* data);
	//! @}

public : //! @name State
	//! @{
	const char* getData() const { return _data; }
	const uint32 getSize() const { return _size; }
	const std::pair<char*, char*>&	getLockedData() const { return _lockedData; }
	const std::pair<uint32, uint32>&	getLockedSize() const { return _lockedSize; }
	const bool isLocked() const { return _locked; }
	//! @}

protected : //! @name Data
	//! @{
	/// Intended usage of the buffer
	Usage _usage;
	/// Size of the buffer in bytes
	uint32 _size;
	/// Software copy of the buffer (for fast access)
	char* _data;
	/// Locked state of the buffer
	bool _locked;
	/// Locked data pointers. The second pointer is for cyclic buffers (ex: sound buffer)
	std::pair<char*, char*> _lockedData;
	/// Locked data size. The second size is for cyclic buffers (ex: sound buffer)
	std::pair<uint32, uint32> _lockedSize;
	//! @}

private : //! @name Friends
	//! @{
	friend std::ostream& operator<< (std::ostream& os, IBuffer& buffer);
	friend std::istream& operator>> (std::istream& is, IBuffer& buffer);
	//! @}
};

class Buffer
{
public :
	enum accesses
	{
		access_read = 0,
		access_write,
		access_readwrite,

		accesses_count
	};

protected :
	Buffer(uint32 size);

protected :
	uint32 m_size;
};

	} // namespace system
} // namespace dw

#include "system/buffer.inl"

#endif // !DW_SYSTEM_BUFFER_H

